Index: applications/party/widget/partymgr/ProfileScreens.xml
===================================================================
--- applications/party/widget/partymgr/ProfileScreens.xml	(révision 1243859)
+++ applications/party/widget/partymgr/ProfileScreens.xml	(copie de travail)
@@ -439,6 +439,9 @@
                         <html-template location="component://party/webapp/partymgr/party/profileblocks/Content.ftl"/>
                     </html>
                 </platform-specific>
+                <screenlet title="${uiLabelMap.PageTitleAddPartyContent}">
+                    <include-form name="UploadPartyContent" location="component://party/widget/partymgr/PartyForms.xml"/>
+                </screenlet>
             </widgets>
         </section>
     </screen>
Index: applications/party/widget/partymgr/PartyForms.xml
===================================================================
--- applications/party/widget/partymgr/PartyForms.xml	(révision 1243859)
+++ applications/party/widget/partymgr/PartyForms.xml	(copie de travail)
@@ -634,6 +634,21 @@
         <field name="updateButton" use-when="content!=null"><submit button-type="button"/></field>
     </form>
 
+    <form name="UploadPartyContent" extends="AddPartyContent">
+        <actions>
+            <set field="content" from-field="nullField"/>
+        </actions>
+        <alt-target use-when="content==null" target="uploadPartyContentJs"/>
+        <field name="dataResourceName"><ignored/></field>
+        <field name="uploadedFile" title="${uiLabelMap.CommonUpload}"><file/></field>
+        <on-event-update-area area-target="partyContentList" event-type="submit" area-id="partyContentList">
+            <parameter param-name="partyId"/>
+        </on-event-update-area>
+        <sort-order>
+            <sort-field name="uploadedFile"/>
+        </sort-order>
+    </form>
+
     <form name="ListPartyContents" type="list" separate-columns="false"
         odd-row-style="alternate-row" default-table-style="basic-table hover-bar">
         <actions>
Index: applications/party/webapp/partymgr/WEB-INF/controller.xml
===================================================================
--- applications/party/webapp/partymgr/WEB-INF/controller.xml	(révision 1243859)
+++ applications/party/webapp/partymgr/WEB-INF/controller.xml	(copie de travail)
@@ -944,11 +944,15 @@
         <response name="error" type="view" value="EventMessages"/>
     </request-map>
 
-    <request-map uri="partyContentList">
+    <request-map uri="uploadPartyContentJs">
         <security auth="true" https="true"/>
-        <response name="success" type="view" value="partyContentList"/>
+        <event type="service" invoke="uploadPartyContentFile"/>
+        <response name="success" type="request" value="jsonUpload"/>
+        <response name="error" type="request" value="jsonUpload"/>
     </request-map>
 
+    <request-map uri="partyContentList"><security auth="true" https="true"/><response name="success" type="view" value="partyContentList"/></request-map>
+
     <request-map uri="img">
         <security auth="false" https="false"/>
         <event type="java" path="org.ofbiz.content.data.DataEvents" invoke="serveImage"/>
Index: framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java
===================================================================
--- framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java	(révision 1243859)
+++ framework/widget/src/org/ofbiz/widget/form/MacroFormRenderer.java	(copie de travail)
@@ -1111,6 +1111,7 @@
         String name = modelFormField.getParameterName(context);
         String buttonType =  submitField.getButtonType();
         String formName = modelForm.getCurrentFormName(context);
+        String formType = modelForm.getType();
         String imgSrc = submitField.getImageLocation(context);
         String confirmation = submitField.getConfirmation(context);
         String className = "";
@@ -1149,6 +1150,8 @@
         sr.append(alert);
         sr.append("\" formName=\"");
         sr.append(formName);
+        sr.append("\" formType=\"");
+        sr.append(formType);
         sr.append("\" title=\"");
         sr.append(encode(title, modelFormField, context));
         sr.append("\" name=\"");
@@ -1394,6 +1397,7 @@
     public void renderFormClose(Appendable writer, Map<String, Object> context, ModelForm modelForm) throws IOException {
         String focusFieldName = modelForm.getfocusFieldName();
         String formName = modelForm.getCurrentFormName(context);
+        String formType = modelForm.getType();
         String containerId = modelForm.getCurrentContainerId(context);
         String hasRequiredField = "";
         for (ModelFormField formField : modelForm.getFieldList()) {
@@ -1408,6 +1412,8 @@
         sr.append(focusFieldName);
         sr.append("\" formName=\"");
         sr.append(formName);
+        sr.append("\" formType=\"");
+        sr.append(formType);
         sr.append("\" containerId=\"");
         sr.append(containerId);
         sr.append("\" hasRequiredField=\"");
Index: framework/widget/templates/htmlFormMacroLibrary.ftl
===================================================================
--- framework/widget/templates/htmlFormMacroLibrary.ftl	(révision 1243859)
+++ framework/widget/templates/htmlFormMacroLibrary.ftl	(copie de travail)
@@ -276,13 +276,13 @@
 </#list>
 </#macro>
 
-<#macro renderSubmitField buttonType className alert formName title name event action imgSrc confirmation containerId ajaxUrl>
+<#macro renderSubmitField buttonType className alert formName formType title name event action imgSrc confirmation containerId ajaxUrl>
 <#if buttonType=="text-link">
  <a <@renderClass className alert /> href="javascript:document.${formName}.submit()" <#if confirmation?has_content>onclick="return confirm('${confirmation?js_string}');"</#if>><#if title?has_content>${title}</#if> </a>
 <#elseif buttonType=="image">
  <input type="image" src="${imgSrc}" <@renderClass className alert /><#if name?has_content> name="${name}"</#if><#if title?has_content> alt="${title}"</#if><#if event?has_content> ${event}="${action}"</#if> <#if confirmation?has_content>onclick="return confirm('${confirmation?js_string}');"</#if>/>
 <#else>
-<input type="<#if containerId?has_content>button<#else>submit</#if>" <@renderClass className alert /><#if name?exists> name="${name}"</#if><#if title?has_content> value="${title}"</#if><#if event?has_content> ${event}="${action}"</#if><#if containerId?has_content> onclick="<#if confirmation?has_content>if (confirm('${confirmation?js_string}')) </#if>ajaxSubmitFormUpdateAreas('${containerId}', '${ajaxUrl}')"<#else><#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}');"</#if></#if>/></#if>
+<input type="<#if containerId?has_content>button<#else>submit</#if>" <@renderClass className alert /><#if name?exists> name="${name}"</#if><#if title?has_content> value="${title}"</#if><#if event?has_content> ${event}="${action}"</#if><#if containerId?has_content> onclick="<#if confirmation?has_content>if (confirm('${confirmation?js_string}')) </#if>ajax<#if formType=="upload">Upload<#else>Submit</#if>FormUpdateAreas('${containerId}', '${ajaxUrl}')"<#else><#if confirmation?has_content> onclick="return confirm('${confirmation?js_string}');"</#if></#if>/></#if>
 </#macro>
 
 <#macro renderResetField className alert name title>
@@ -304,8 +304,10 @@
 <#macro renderSingleFormFieldTitle></#macro>
 
 <#macro renderFormOpen linkUrl formType targetWindow containerId containerStyle autocomplete name viewIndexField viewSizeField viewIndex viewSize useRowSubmit>
-
     <form method="post" action="${linkUrl}"<#if formType=="upload"> enctype="multipart/form-data"</#if><#if targetWindow?has_content> target="${targetWindow}"</#if><#if containerId?has_content> id="${containerId}"</#if> class=<#if containerStyle?has_content>"${containerStyle}"<#else>"basic-form"</#if> onsubmit="javascript:submitFormDisableSubmits(this)"<#if autocomplete?has_content> autocomplete="${autocomplete}"</#if> name="${name}"><#lt/>
+    <#if formType?has_content && formType=="upload">
+        <div id="fields_${containerId}">
+    </#if>
     <#if useRowSubmit?has_content && useRowSubmit>
         <input type="hidden" name="_useRowSubmit" value="Y"/>
         <#if linkUrl?index_of("VIEW_INDEX") &lt;= 0 && linkUrl?index_of(viewIndexField) &lt;= 0>
@@ -316,7 +318,10 @@
         </#if>
     </#if>
 </#macro>
-<#macro renderFormClose focusFieldName formName containerId hasRequiredField>
+<#macro renderFormClose focusFieldName formName formType containerId hasRequiredField>
+    <#if formType?has_content && formType=="upload">
+        </div>
+    </#if>
     </form><#lt/>
     <#if focusFieldName?has_content>
         <script language="JavaScript" type="text/javascript">
Index: framework/common/widget/CommonScreens.xml
===================================================================
--- framework/common/widget/CommonScreens.xml	(révision 1243859)
+++ framework/common/widget/CommonScreens.xml	(copie de travail)
@@ -117,6 +117,7 @@
                 <set field="layoutSettings.javaScripts[+0]" value="${groovy: org.ofbiz.common.JsLanguageFilesMapping.validation.getFilePath(initialLocaleComplete)}" global="true" />
                 <set field="layoutSettings.javaScripts[+0]" value="${groovy: org.ofbiz.common.JsLanguageFilesMapping.dateTime.getFilePath(initialLocaleComplete)}" global="true" />
                 <set field="layoutSettings.javaScripts[+0]" value="/images/jquery/plugins/asmselect/jquery.asmselect-1.0.4a-beta.js" global="true" />
+                <set field="layoutSettings.javaScripts[+0]" value="/images/jquery/plugins/jquery.upload.js" global="true"/>
                 <set field="layoutSettings.javaScripts[+0]" value="/images/jquery/plugins/datetimepicker/jquery-ui-timepicker-addon-0.9.7.js" global="true" />
                 <set field="layoutSettings.javaScripts[+0]" value="/images/jquery/plugins/jquery.maskedinput-1.2.2.min.js" global="true" />
                 <set field="layoutSettings.javaScripts[+0]" value="/images/jquery/ui/js/jquery-ui-1.8.16.custom.min.js" global="true" />
Index: framework/common/webcommon/WEB-INF/common-controller.xml
===================================================================
--- framework/common/webcommon/WEB-INF/common-controller.xml	(révision 1243859)
+++ framework/common/webcommon/WEB-INF/common-controller.xml	(copie de travail)
@@ -184,6 +184,11 @@
         <event type="java" path="org.ofbiz.common.CommonEvents" invoke="jsonResponseFromRequestAttributes"/>
         <response name="success" type="none"/>
     </request-map>
+    <request-map uri="jsonUpload">
+        <security direct-request="false"/>
+        <event type="java" path="org.ofbiz.common.CommonEvents" invoke="jsonUploadResponseFromRequestAttributes"/>
+        <response name="success" type="none"/>
+    </request-map>
 
     <request-map uri="showHelp">
         <security https="true" auth="true"/>
Index: framework/common/src/org/ofbiz/common/CommonEvents.java
===================================================================
--- framework/common/src/org/ofbiz/common/CommonEvents.java	(révision 1243859)
+++ framework/common/src/org/ofbiz/common/CommonEvents.java	(copie de travail)
@@ -264,7 +264,22 @@
         return "success";
     }
 
+    public static String jsonUploadResponseFromRequestAttributes(HttpServletRequest request, HttpServletResponse response) {
+        // pull out the service response from the request attribute
+        Map<String, Object> attrMap = UtilHttp.getJSONAttributeMap(request);
+
+        // create a JSON Object for return
+        JSONObject json = JSONObject.fromObject(attrMap);
+        writeJSONtoResponse(json, response, "text/html"); //text-html since jquery.upload don't work wit contentType application/x-json : http://lagoscript.org/jquery/upload/documentation
+
+        return "success";
+    }
+
     private static void writeJSONtoResponse(JSON json, HttpServletResponse response) {
+        writeJSONtoResponse(json, response, "application/x-json");
+    }
+
+    private static void writeJSONtoResponse(JSON json, HttpServletResponse response, String contentType ) {
         String jsonStr = json.toString();
         if (jsonStr == null) {
             Debug.logError("JSON Object was empty; fatal error!", module);
@@ -272,7 +287,7 @@
         }
 
         // set the X-JSON content type
-        response.setContentType("application/x-json");
+        response.setContentType(contentType);
         // jsonStr.length is not reliable for unicode characters
         try {
             response.setContentLength(jsonStr.getBytes("UTF8").length);
Index: framework/images/webapp/images/selectall.js
===================================================================
--- framework/images/webapp/images/selectall.js	(révision 1243859)
+++ framework/images/webapp/images/selectall.js	(copie de travail)
@@ -384,6 +384,45 @@
    });
 }
 
+/** Submit form, update multiple areas (HTML container elements).
+ * @param form The form element
+ * @param areaCsvString The area CSV string. The CSV string is a flat array in the
+ * form of: areaId, target, target parameters [, areaId, target, target parameters...].
+*/
+function ajaxUploadFormUpdateAreas(form, areaCsvString) {
+       waitSpinnerShow();
+       hideErrorContainer = function() {
+           jQuery('#content-messages').removeClass('errorMessage').fadeIn('fast');
+       }
+       updateFunction = function(data) {
+           if (data._ERROR_MESSAGE_LIST_ != undefined || data._ERROR_MESSAGE_ != undefined) {
+               if(!jQuery('#content-messages')) {
+                  //add this div just after app-navigation
+                  if(jQuery('#content-main-section')){
+                      jQuery('#content-main-section' ).before('<div id="content-messages" onclick="hideErrorContainer()"></div>');
+                  }
+               }
+               jQuery('#content-messages').addClass('errorMessage');
+              if (data._ERROR_MESSAGE_LIST_ != undefined && data._ERROR_MESSAGE_ != undefined) {
+                  jQuery('#content-messages' ).html(data._ERROR_MESSAGE_LIST_ + " " + data._ERROR_MESSAGE_);
+              } else if (data._ERROR_MESSAGE_LIST_ != undefined) {
+                  jQuery('#content-messages' ).html(data._ERROR_MESSAGE_LIST_);
+              } else {
+                  jQuery('#content-messages' ).html(data._ERROR_MESSAGE_);
+              }
+              jQuery('#content-messages').fadeIn('fast');
+           }else {
+               if(jQuery('#content-messages')) {
+                   jQuery('#content-messages').removeClass('errorMessage').fadeIn("fast");
+               }
+               ajaxUpdateAreas(areaCsvString);
+           }
+           waitSpinnerHide();
+       }
+
+   jQuery("#fields_" + form).upload(jQuery("#" + form).attr("action"), function(data) {updateFunction(data)}, 'json');
+}
+
 /** Enable auto-completion for text elements.
  * @param areaCsvString The area CSV string. The CSV string is a flat array in the
  * form of: areaId, target, target parameters [, areaId, target, target parameters...].
Index: framework/images/webapp/images/jquery/plugins/jquery.upload.js
===================================================================
--- framework/images/webapp/images/jquery/plugins/jquery.upload.js	(révision 0)
+++ framework/images/webapp/images/jquery/plugins/jquery.upload.js	(révision 0)
@@ -0,0 +1,133 @@
+/*
+ * jQuery.upload v1.0.2
+ *
+ * Copyright (c) 2010 lagos
+ * Dual licensed under the MIT and GPL licenses.
+ *
+ * http://lagoscript.org
+ */
+(function($) {
+
+	var uuid = 0;
+
+	$.fn.upload = function(url, data, callback, type) {
+		var self = this, inputs, checkbox, checked,
+			iframeName = 'jquery_upload' + ++uuid,
+			iframe = $('<iframe name="' + iframeName + '" style="position:absolute;top:-9999px" />').appendTo('body'),
+			form = '<form target="' + iframeName + '" method="post" enctype="multipart/form-data" />';
+
+		if ($.isFunction(data)) {
+			type = callback;
+			callback = data;
+			data = {};
+		}
+
+		checkbox = $('input:checkbox', this);
+		checked = $('input:checked', this);
+		form = self.wrapAll(form).parent('form').attr('action', url);
+
+		// Make sure radios and checkboxes keep original values
+		// (IE resets checkd attributes when appending)
+		checkbox.removeAttr('checked');
+		checked.attr('checked', true);
+
+		inputs = createInputs(data);
+		inputs = inputs ? $(inputs).appendTo(form) : null;
+
+		form.submit(function() {
+			iframe.load(function() {
+				var data = handleData(this, type),
+					checked = $('input:checked', self);
+
+				form.after(self).remove();
+				checkbox.removeAttr('checked');
+				checked.attr('checked', true);
+				if (inputs) {
+					inputs.remove();
+				}
+
+				setTimeout(function() {
+					iframe.remove();
+					if (type === 'script') {
+						$.globalEval(data);
+					}
+					if (callback) {
+						callback.call(self, data);
+					}
+				}, 0);
+			});
+		}).submit();
+
+		return this;
+	};
+
+	function createInputs(data) {
+		return $.map(param(data), function(param) {
+			return '<input type="hidden" name="' + param.name + '" value="' + param.value + '"/>';
+		}).join('');
+	}
+
+	function param(data) {
+		if ($.isArray(data)) {
+			return data;
+		}
+		var params = [];
+
+		function add(name, value) {
+			params.push({name:name, value:value});
+		}
+
+		if (typeof data === 'object') {
+			$.each(data, function(name) {
+				if ($.isArray(this)) {
+					$.each(this, function() {
+						add(name, this);
+					});
+				} else {
+					add(name, $.isFunction(this) ? this() : this);
+				}
+			});
+		} else if (typeof data === 'string') {
+			$.each(data.split('&'), function() {
+				var param = $.map(this.split('='), function(v) {
+					return decodeURIComponent(v.replace(/\+/g, ' '));
+				});
+
+				add(param[0], param[1]);
+			});
+		}
+
+		return params;
+	}
+
+	function handleData(iframe, type) {
+		var data, contents = $(iframe).contents().get(0);
+
+		if ($.isXMLDoc(contents) || contents.XMLDocument) {
+			return contents.XMLDocument || contents;
+		}
+		data = $(contents).find('body').html();
+
+		switch (type) {
+			case 'xml':
+				data = parseXml(data);
+				break;
+			case 'json':
+				data = window.eval('(' + data + ')');
+				break;
+		}
+		return data;
+	}
+
+	function parseXml(text) {
+		if (window.DOMParser) {
+			return new DOMParser().parseFromString(text, 'application/xml');
+		} else {
+			var xml = new ActiveXObject('Microsoft.XMLDOM');
+			xml.async = false;
+			xml.loadXML(text);
+			return xml;
+		}
+	}
+
+})(jQuery);
